#include <stdio.h>

// 将传入的指针类型强制转为int型， 再取值进行比较
int int_cmp(void *x, void *y) {
    return *((int *)x) - *((int *)y);
}

// 将传入的指针类型强制转为char型， 再取值进行比较
int char_cmp(void *x, void *y) {
    return *((char *)x) - *((char *)y);
}

// 由于不知道要对调的数据是什么类型，所以此处采用逐字节转换的方式来对调数据
// 根据传入的字节数， 将传入的指针逐字节移动
// 将每个字节的指针强转为char型，取出每个字节的内容后对调
void swap(void *x, void *y, int el_size) {
    for (int i = 0; i < el_size; i++) {
        char tmp = *((char *)x + i);
        *((char *)x + i) = *((char *)y + i);
        *((char *)y + i) = tmp;
    }
}

/**
 * 冒泡排序
 */
void reorder(void *arr, int el_size, int (*cmp)(void *x, void *y),  int len)
{
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - 1 - i; j++) {
            // 1) 将未知的数组元素指针强转为char型
            // 2) 再根据传入的单个元素字节数 乘以j算出要使用的元素的地址
            char * tmp_x = (char *)arr + j * el_size;
            char * tmp_y = (char *)arr + (j + 1) * el_size;

            // printf("tmp_x = %d tmp_y = %d\n", *tmp_x, *tmp_y);

           if (cmp(tmp_x, tmp_y) > 0) {    
              swap(tmp_x, tmp_y, el_size); 
           }
        }
    }
}

int main(int argc, char *argv[])
{
    // int arr[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
    char arr[] = {'c', 'a', 'd', 'e', 'b', 'f', 'j'};
    int len = sizeof(arr) / sizeof(arr[0]);
    int el_size = sizeof(arr[0]);

    reorder(arr, el_size, char_cmp, len);

    for (int i = 0; i < len; i++) {
        printf("%c ", arr[i]);
    }

    puts("");

    return 0;
}



